package com.gluck.cases.app.biz.impl.excel;

import com.gluck.cases.common.utils.annotations.TestCaseField;
import com.gluck.cases.core.modal.dto.TestCaseDTO;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;

/**
 * @ClassName CreateWorkBookHandle
 * @Desc excel 行handle
 * @Author shiyongzhe
 * @Date 2022/5/24 - 6:06 下午
 **/
public class CreateRowsHandler extends AbstractExcelHandler<Workbook> {


    private CellStyle cellStyle;

    // 字段换行
    private Integer STRING_LIMIT = 20;

    @Override
    public void doHandler(Workbook wb, Builder<Workbook> excelBuilder) {
       try{
           List<TestCaseDTO> cases = excelBuilder.getCases();
           Sheet sheet = wb.getSheet(excelBuilder.getSheetname());
           cellStyle = wb.createCellStyle();
           cellStyle.setWrapText(true);
           for (int i = 0; i < cases.size(); i ++){
               // step 1 构建单元行
               Row row = sheet.createRow(i);
               // step 2 单元格第一行标题
               if(i == 0){
                   builderCellsTitle(row);
                   continue;
               }
               // step3 构建单元格数据
               builderCells(row, cases.get(i));
           }
           sheet.setDefaultColumnWidth(STRING_LIMIT);
           nextHandler.doHandler(wb, excelBuilder);
       }catch (Exception e){
           e.printStackTrace();
       }
    }

    /**
     * 功能描述: 构建第一行标题
     * @Params [row]
     * @Return void
     * @Author I`m Gluck
     * @Date 2022/5/24
     */
    private void builderCellsTitle(Row row) {
        Class<?> clazz = TestCaseDTO.class;
        Field[] fields = clazz.getDeclaredFields();
        AtomicInteger index = new AtomicInteger(0);
        for (Field field : fields){
            int i = index.getAndIncrement();
            TestCaseField testCaseField = field.getAnnotation(TestCaseField.class);
            if(Objects.isNull(testCaseField)){
               continue;
            }
            String fieldName = testCaseField.fieldName();
            String name = testCaseField.name();
            String title = name + "/" + fieldName;
            Cell cell = row.createCell(i, Cell.CELL_TYPE_STRING);
            cell.setCellValue(title.trim());
        }
    }

    /**
     * 功能描述: 构建单元格
     * @Params [row, cases]
     * @Return void
     * @Author I`m Gluck
     * @Date 2022/5/24
     */
    private void builderCells(Row row, TestCaseDTO cases) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
        Class<?> clazz = TestCaseDTO.class;
        Field[] fields = clazz.getDeclaredFields();
        for (int f = 0; f < fields.length; f ++){
            Class<?> type = fields[f].getType();
            PropertyDescriptor descriptor = new PropertyDescriptor(fields[f].getName(), cases.getClass());
            Method readMethod = descriptor.getReadMethod();
            Object value = readMethod.invoke(cases);
            createCellAndType(type, row, f, value);
        }
    }

    /**
     * 功能描述: set 单元值
     * @Params [type, row, cellnum, value]
     * @Return org.apache.poi.ss.usermodel.Cell
     * @Author I`m Gluck
     * @Date 2022/5/24
     */
    private Cell createCellAndType(Class<?> type, Row row, int cellnum, Object value) {
        Integer cellType = Cell.CELL_TYPE_STRING;
        Cell cell = row.createCell(cellnum, cellType);
        String normalValue = (String) value;
        if(!StringUtils.isEmpty(normalValue)){
            String s = displayWithComma(normalValue.trim(), "\r\n", STRING_LIMIT);
            cell.setCellValue(s);
        }
        cell.setCellValue(normalValue);

        if(type.equals(String.class) && !StringUtils.isEmpty(normalValue)){
            float excelCellAutoHeight = getExcelCellAutoHeight((String) value, 8f);
            row.setHeightInPoints(excelCellAutoHeight);
        }
        if(type.equals(Integer.class)){
            cellType = Cell.CELL_TYPE_NUMERIC;
            cell = row.createCell(cellnum, cellType);
            cell.setCellValue((Integer)value);
        }
        if(type.equals(Boolean.class)){
            cellType = Cell.CELL_TYPE_BOOLEAN;
            cell = row.createCell(cellnum, cellType);
            cell.setCellValue((Boolean) value);
        }
        cell.setCellStyle(cellStyle);
        return cell;
    }

    /**
     * 功能描述: str 是单元格需要放入的 字符串 fontCountInline 是该单元格每行多少个汉字 全角为1 英文或符号为0.5
     * @Params [str, fontCountInline]
     * @Return float
     * @Author I`m Gluck
     * @Date 2022/5/24
     */
    public static float getExcelCellAutoHeight(String str, float fontCountInline) {
        float defaultRowHeight = 12.00f;//每一行的高度指定
        float defaultCount = 0.00f;
        for (int i = 0; i < str.length(); i++) {
            float ff = getregex(str.substring(i, i + 1));
            defaultCount = defaultCount + ff;
        }
        return ((int) (defaultCount / fontCountInline) + 1) * defaultRowHeight;//计算
    }

    public static float getregex(String charStr) {

        if(charStr==" ")
        {
            return 0.5f;
        }
        // 判断是否为字母或字符
        if (Pattern.compile("^[A-Za-z0-9]+$").matcher(charStr).matches()) {
            return 0.5f;
        }
        // 判断是否为全角
        if (Pattern.compile("[\u4e00-\u9fa5]+$").matcher(charStr).matches()) {
            return 1.00f;
        }
        //全角符号 及中文
        if (Pattern.compile("[^x00-xff]").matcher(charStr).matches()) {
            return 1.00f;
        }
        return 0.5f;
    }

    /**
     * 将字符串从右至左每 N 位加一 "-"
     * @param str 需要加逗号的字符串
     * @param sign 需要追加字符 例如：- 、* 、@ 、| 、# 、：、￥ 等等
     * @param n 隔几位字符加 "-' 例如：n=2  即：93:21:53:45:65:43
     *          例如：n=2  即：93:21:53:45:65:43
     *               n=3  即：932:534:565:431
     * @return 以从右至左每隔 N 位加一逗号显示
     */
    public static String displayWithComma(String str, String sign, int n) {
        StringBuilder builder = new StringBuilder();

        // 每 n 位取一长度
        int size = (str.length() % n == 0) ? (str.length() / n) : (str.length() / n + 1);
        /*
         * 比如把一段字符串分成 n 段,第 n 段可能不是三个数,有可能是一个或者两个,
         * 现将字符串分成两部分.一部分为前 n-1 段,第二部分为第 n 段.前 n-1 段，每一段加一 "-" .而第 n 段直接取出即可
         */
        for (int i = 0; i < size - 1; i++) { // 前n-1段
            builder.append(str, i * n, i * n + n).append(sign);
        }

        for (int i = size - 1; i < size; i++) { // 第n段
            builder.append(str.substring(i * n));
        }

        builder = new StringBuilder(new StringBuffer(builder.toString()));
        System.out.println("builder = " + builder);
        return builder.toString();
    }

}
